package com.hexinfo.dmpro.component.code.detection.utils;


import cn.hutool.core.util.ArrayUtil;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

/**
 * @Package: com.hex.hdtp.scf.oracle.utils
 * @ClassName AntlrUtil
 * @Description: antlr相关工具类
 * @Author: Dong shiyi
 * @Date 2023/6/26 11:10
 * @Version v1.0
 **/
public class AntlrUtil {

    public AntlrUtil() {
        throw new Error("do not create this object");
    }


    /**
     * @Method: assembleChildren <br>
     * @Param: [parseTree] <br>
     * @Return: java.lang.String <br>
     * @Description：拼接节点信息（单一节点下钻）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/20 19:32 <br>
     * @Version： V1.0<br>
     */
    public static String assembleChildren(final ParseTree parseTree) {
        return queryDesignateChildrenText(parseTree, new StringBuilder());
    }

    /**
     * @Method: assembleChildren <br>
     * @Param:
     * @param parseTree         拼接节点起始位
     * @param noAssembleChildren 拼接过程中需忽略的节点class <br>
     * @Return: java.lang.String <br>
     * @Description：拼接节点信息，但会忽略 noAssembleChildren 输入的class （单一节点下钻）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/1 17:43 <br>
     * @Version： V1.0<br>
     */
    public static String assembleChildren(final ParseTree parseTree, final Class<?>... noAssembleChildren) {
        return queryDesignateChildrenText(parseTree, new StringBuilder(), noAssembleChildren);
    }


    /**
     * @Method: queryDesignateParant <br>
     * @Param: [thisParseTree, targetClass] <br>
     * @Return: boolean <br>
     * @Description：向上 查找指定父级class是否存在<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/6/20 11:52 <br>
     * @Version： V1.0<br>
     */
    public static boolean queryDesignateParent(final ParseTree thisParseTree, final Class<?> targetClass) {
        return queryDesignateParent(thisParseTree, targetClass, null);
    }

    /**
     * @Method: queryDesignateParant <br>
     * @Param:
     * @param thisParseTree      当前节点
     * @param targetClass        目标节点
     * @param queryParseTreeOver 查找的结束点，如未设置则到最上层 <br>
     * @Return: boolean <br>
     * @Description：<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/3 13:57 <br>
     * @Version： V1.0<br>
     */
    public static boolean queryDesignateParent(final ParseTree thisParseTree
            , final Class<?> targetClass
            , final Class<?>... queryParseTreeOver) {

        return queryDesignateParentObject(thisParseTree, targetClass, queryParseTreeOver) != null;
    }

    /**
     * @Method: queryDesignateParantObject <br>
     * @Param: [thisParseTree, targetClass, noPathRuleContexts] <br>
     * @Return: org.antlr.v4.runtime.tree.ParseTree <br>
     * @Description：查找指定class的父级对象，无则返回空<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/26 11:54 <br>
     * @Version： V1.0<br>
     */
    public static ParseTree queryDesignateParentObject(final ParseTree thisParseTree
            , final Class<?> targetClass
            , final Class<?>... queryParseTreeOver) {
        final ParseTree thisParseTreeParent = thisParseTree.getParent();
        if (thisParseTreeParent == null) {
            return null;
        } else if (ArrayUtil.isNotEmpty(queryParseTreeOver)
                && ArrayUtil.containsAny(queryParseTreeOver, thisParseTreeParent.getClass())) {
            return null;
        } else if (thisParseTreeParent.getClass() == targetClass) {
            return thisParseTreeParent;
        } else {
            return queryDesignateParentObject(thisParseTreeParent, targetClass, queryParseTreeOver);
        }
    }

    /**
     * @Method: queryDesignateParantText <br>
     * @Param: [thisParseTree, targetClass] <br>
     * @Return: java.lang.String <br>
     * @Description：指定 parent 对应的表<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/12 11:00 <br>
     * @Version： V1.0<br>
     */
    public static String queryDesignateParentText(final ParseTree thisParseTree, final Class<?> targetClass) {
        String resultStr = "";
        final ParseTree thisParseTreeParent = thisParseTree.getParent();
        if (thisParseTreeParent == null) {
            return "";
        } else if (thisParseTreeParent.getClass() == targetClass) {
            return thisParseTreeParent.getText();
        } else {
            return queryDesignateParentText(thisParseTreeParent, targetClass);
        }
    }

    /**
     * @Method: queryDesignateParantCount <br>
     * @Param: [thisParseTree, iterateCount, targetClass] <br>
     * @Return: int <br>
     * @Description：统计 parseTree 中 指定class 的数量<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/18 17:12 <br>
     * @Version： V1.0<br>
     */
    public static int queryDesignateParentCount(final ParseTree thisParseTree, final int iterateCount, final Class<?>... targetClass) {
        int resultCount = iterateCount;
        final ParseTree thisParseTreeParent = thisParseTree.getParent();
        if (thisParseTreeParent == null) {
            return resultCount;
        } else if (ArrayUtil.containsAny(targetClass, thisParseTree.getClass())) {
            resultCount++;
        }
        return queryDesignateParentCount(thisParseTreeParent, resultCount, targetClass);
    }

    /**
     * @Method: queryDesignateChildren <br>
     * @Param: [parseTree, targetClass] <br>
     * @Return: boolean <br>
     * @Description：用于判断 指定class 是否在 parseTree 中（单一节点下钻）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/18 17:11 <br>
     * @Version： V1.0<br>
     */
    public static boolean queryDesignateChildren(final ParseTree parseTree, final Class<?> targetClass) {
        final int childCount = parseTree.getChildCount();
        if (childCount == 0) {
            return false;
        }
        for (int i = 0; i < childCount; i++) {
            final ParseTree child = parseTree.getChild(i);
            if (child.getClass() == targetClass) {
                return true;
            }
            return queryDesignateChildren(child, targetClass);
        }
        return false;
    }


    /**
     * @Method: queryDesignateChildrenTextOfSum <br>
     * @Param: [parseTree, targetClass] <br>
     * @Return: java.util.List<org.antlr.v4.runtime.tree.ParseTree> <br>
     * @Description：获取指定 class 节点集合（所有节点）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/18 17:10 <br>
     * @Version： V1.0<br>
     */
    public static List<ParseTree> queryDesignateChildrenOfSumObj(final ParseTree parseTree, final Class<?>... targetClasses) {
        return queryDesignateChildrenOfSumObj(parseTree, true, targetClasses);
    }

    /**
     * @Method: queryNotDesignateChildrenOfSumObj <br>
     * @Param:
     * @param parseTree
     * @param noAssembleChildren <br>
     * @Return: java.util.List<org.antlr.v4.runtime.tree.ParseTree> <br>
     * @Description：查找 非指定节点 的 节点集合（所有节点）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/7 11:55 <br>
     * @Version： V1.0<br>
     */
    public static List<ParseTree> queryNotDesignateChildrenOfSumObj(final ParseTree parseTree, final Class<?>... noAssembleChildren) {
        return queryDesignateChildrenOfSumObj(parseTree, false, noAssembleChildren);
    }


    /**
     * @Method: assembleChildrenOfSum <br>
     * @Param:
     * @param parseTree 当前节点 <br>
     * @Return: java.lang.String <br>
     * @Description：当前节点下 节点拼接（所有节点） <br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/7 17:49 <br>
     * @Version： V1.0<br>
     */
    public static String assembleChildrenOfSumText(final ParseTree parseTree) {
        return queryDesignateChildrenOfSumText(parseTree,true);
    }

    /**
     * @Method: assembleChildrenOfSumText <br>
     * @Param:
     * @param parseTree 当前节点
     * @param noAssembleChildren 需要忽略的不拼凑节点<br>
     * @Return: java.lang.String <br>
     * @Description：当前节点下 节点拼接（所有节点），但会忽略 noAssembleChildren <br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/7 17:51 <br>
     * @Version： V1.0<br>
     */
    public static String assembleChildrenOfSumText(final ParseTree parseTree, final Class<?>... noAssembleChildren) {
        return queryDesignateChildrenOfSumText(parseTree,true,noAssembleChildren);
    }


    private static List<ParseTree> queryDesignateChildrenOfSumObj(final ParseTree parseTree, final boolean isContains, final Class<?>... classes) {
        final List<ParseTree> resultList = new ArrayList<>(10);
        final Queue<ParseTree> queue = new LinkedList<>();
        queue.offer(parseTree);
        while (!queue.isEmpty()) {
            final ParseTree currNode = queue.poll();
            if (ArrayUtil.isEmpty(classes) || ArrayUtil.contains(classes, currNode.getClass()) == isContains) {
                resultList.add(currNode);
            }

            for (int i = 0; i < currNode.getChildCount(); i++) {
                final ParseTree child = currNode.getChild(i);
                if (!(child instanceof TerminalNodeImpl)) {
                    queue.offer(child);
                }
            }
        }
        return resultList;
    }





    /**
     * @param parseTree
     * @param targetClasses <br>
     * @Method: queryDesignateChildrenTextOfSumObj <br>
     * @Param:
     * @Return: java.util.List<org.antlr.v4.runtime.tree.ParseTree> <br>
     * @Description：查找 指定节点 的 所有文本集合<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/4 16:54 <br>
     * @Version： V1.0<br>
     */
    public static String queryDesignateChildrenOfSumText(final ParseTree parseTree, final Class<?>... targetClasses) {
        return queryDesignateChildrenOfSumText(parseTree, true, targetClasses);
    }

    /**
     * @param parseTree
     * @param noAssembleChildren <br>
     * @Method: queryNotDesignateChildrenOfSumText <br>
     * @Param:
     * @Return: java.lang.String <br>
     * @Description：查找 非指定节点 的 所有文本集合<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/7 11:35 <br>
     * @Version： V1.0<br>
     */
    public static String queryNotDesignateChildrenOfSumText(final ParseTree parseTree, final Class<?>... noAssembleChildren) {
        return queryDesignateChildrenOfSumText(parseTree, false, noAssembleChildren);
    }


    /**
     * @Method: queryDesignateChildrenOfSumText <br>
     * @Param:
     * @param parseTree
     * @param isContains
     * @param classes <br>
     * @Return: java.lang.String <br>
     * @Description：获取<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/8/7 11:44 <br>
     * @Version： V1.0<br>
     */
    private static String queryDesignateChildrenOfSumText(final ParseTree parseTree, final boolean isContains, final Class<?>... classes) {
        final StringBuilder builder = new StringBuilder();
        final Queue<ParseTree> queue = new LinkedList<>();
        queue.offer(parseTree);
        while (!queue.isEmpty()) {
            final ParseTree currNode = queue.poll();
            if (ArrayUtil.isEmpty(classes) || ArrayUtil.contains(classes, currNode.getClass()) == isContains) {
                builder.append(assembleChildren(currNode));
            }

            for (int i = 0, size = currNode.getChildCount(); i < size; i++) {
                final ParseTree child = currNode.getChild(i);
                if (!(child instanceof TerminalNodeImpl)) {
                    queue.offer(child);
                }
            }
        }
        return builder.toString();
    }


    /**
     * @Method: queryDesignateChildrenText <br>
     * @Param: [parseTree, targetClass] <br>
     * @Return: java.lang.String <br>
     * @Description：获取指定class的getText<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/18 18:11 <br>
     * @Version： V1.0<br>
     */
    public static String queryDesignateChildrenText(final ParseTree parseTree, final Class<?> targetClass) {
        final int childCount = parseTree.getChildCount();
        if (childCount == 0) {
            return "";
        }
        for (int i = 0; i < childCount; i++) {
            final ParseTree child = parseTree.getChild(i);
            if (child.getClass() == targetClass) {
                return child.getText();
            }
            return queryDesignateChildrenText(child, targetClass);
        }
        return "";
    }

    /**
     * @Method: queryDesignateChildrenText <br>
     * @Param: [parseTree, builder] <br>
     * @Return: java.lang.String <br>
     * @Description：获取从当前 parseTree 树状结构中每一个子节点的最后一个节点的 getText，并进行拼凑（单一节点，不会处理同级节点）<br>
     * @Author： Dong shiyi<br>
     * @Date： 2023/7/18 18:08 <br>
     * @Version： V1.0<br>
     */
    public static String queryDesignateChildrenText(final ParseTree parseTree, final StringBuilder builder, Class<?>... noAssembleChildren) {
        final int childCount = parseTree.getChildCount();
        if (childCount == 0 || ArrayUtil.contains(noAssembleChildren, parseTree.getClass())) {
            return "";
        }
        for (int i = 0; i < childCount; i++) {
            final ParseTree child = parseTree.getChild(i);
            if (child.getChildCount() == 0) {
                if (ArrayUtil.contains(noAssembleChildren, child.getClass())) {
                    continue;
                }
                builder.append(child.getText()).append(" ");
            }
            queryDesignateChildrenText(child, builder, noAssembleChildren);
        }
        return builder.toString();
    }

    /**
     * @Method countContextNum
     * @param context
     * @param targetClass
     * @return int
     * @Description 查询上级指定节点个数
     * @Author jian.qiao
     * @Date 2023/8/7 15:46
     * @Version V1.0
     */
    public static int countContextNum(ParserRuleContext context, final Class<?> targetClass) {
        // 初始化计数为0
        int count = 0;

        // 如果当前节点是QueryBlockContext类型，则增加计数器
        if (context.getClass() == targetClass) {
            count++;
        }

        // 检查父节点
        ParserRuleContext parent = context.getParent();
        if (parent != null) {
            count += countContextNum(parent, targetClass);
        }

        return count;
    }

}
